package fr.inserm.umr915.vcfserver.bio.ucsc.generic;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;

import fr.inserm.umr915.vcfserver.bio.Segment;
import fr.inserm.umr915.vcfserver.bio.berkeley.DatabaseManager;
import fr.inserm.umr915.vcfserver.xml.XmlStreamSerializer;

public class GenericEntityHandler
	extends DatabaseManager<GenericEntityHandler.GenericEntity>
	{
	private Binding dataBinding=new Binding();
	private StaxSerializer stax=new StaxSerializer();
	private int nameColumn=-1;
	private int chromColumn=-1;
	private int startColumn=-1;
	private int endColumn=-1;
	private boolean saveName=false;
	
	public class GenericEntity
		{
		private String name;
		private String chromosome;
		private int start;
		private int end;
		}
	
	private class Binding extends TupleBinding<GenericEntity>
		{
		@Override
		public GenericEntity entryToObject(TupleInput in)
			{
			GenericEntity e=new GenericEntity();
			e.chromosome=in.readString();
			e.start=in.readInt();
			if(endColumn!=-1)
				{
				e.end=in.readInt();
				}
			else
				{
				e.end=e.start+1;
				}
			if(nameColumn!=-1)
				{
				e.name= in.readString();
				}
			
			return e;
			}
		@Override
		public void objectToEntry(GenericEntity o, TupleOutput out)
			{
			out.writeString(o.chromosome);
			out.writeInt(o.start);
			if(endColumn!=-1)
				{
				out.writeInt(o.end);
				}
			if(nameColumn!=-1)
				{
				out.writeString(o.name);
				}
			}
		}
	
	private class StaxSerializer implements XmlStreamSerializer<GenericEntity>
		{
		@Override
		public void write(GenericEntity o, XMLStreamWriter out)
				throws XMLStreamException
			{
			out.writeStartElement(getJavaName());
			
			out.writeStartElement("chrom");
			out.writeCharacters(o.chromosome);
			out.writeEndElement();
			
			out.writeStartElement("chromStart");
			out.writeCharacters(String.valueOf(o.start));
			out.writeEndElement();
			
			out.writeStartElement("chromEnd");
			out.writeCharacters(String.valueOf(o.end));
			out.writeEndElement();
			
			if(o.name!=null && !o.name.isEmpty())
				{
				out.writeStartElement("name");
				out.writeCharacters(o.name);
				out.writeEndElement();
				}
		
			
			out.writeEndElement();
			}
		}
		
	public GenericEntityHandler()
		{

		}
	
	
	
	
	public int getNameColumn() {
		return nameColumn;
	}




	public void setNameColumn(int nameColumn) {
		this.nameColumn = nameColumn;
	}




	public int getChromColumn() {
		return chromColumn;
	}




	public void setChromColumn(int chromColumn) {
		this.chromColumn = chromColumn;
	}




	public int getChromStartColumn() {
		return startColumn;
	}




	public void setChromStartColumn(int startColumn) {
		this.startColumn = startColumn;
	}




	public int getChromEndColumn() {
		return endColumn;
	}




	public void setChromEndColumn(int endColumn) {
		this.endColumn = endColumn;
	}




	public boolean isSaveName() {
		return saveName;
	}




	public void setSaveName(boolean saveName) {
		this.saveName = saveName;
	}




	public String getJavaName()
		{
		return getName().substring(0,1).toUpperCase()+getName().substring(1);
		}
		
	@Override
	public TupleBinding< GenericEntity> getDataBinding()
		{
		return this.dataBinding;
		}
		
	@Override
	public XmlStreamSerializer<GenericEntity> getXmlStreamSerializer()
		{
		return stax;
		}
	
	@Override
	protected Set<String> getNames(GenericEntity o)
		{
		Set<String> set=new HashSet<String>();
		if(this.nameColumn!=-1 && o.name!=null && saveName) set.add(o.name);
		return set;
		}
		
	@Override
	public GenericEntity parse(String line) throws IOException
		{
		String tokens[]=getDelim().split(line);
		GenericEntity g= new GenericEntity();
		g.chromosome=tokens[this.chromColumn];
		if(this.nameColumn!=-1)
			{
			g.name=tokens[this.nameColumn];
			}
		g.start=Integer.parseInt(tokens[this.startColumn]);
		if(this.endColumn!=-1)
			{
			g.end=Integer.parseInt(tokens[this.endColumn]);
			}
		else
			{
			g.end=g.start+1;
			}
		return g;
		}
	@Override
	public Segment getSegment(GenericEntity o) {
		return new Segment(o.chromosome,o.start,o.end);
		}
	}